﻿using lwzlz.Application.Enums;
using lwzlz.Common;
using lwzlz.Common.VerifyCode;
using lwzlz.Core;
using lwzlz.Core.Repository;
using System;
using System.Collections;
using System.Linq;
using System.Web;

namespace lwzlz.Application.System
{
    public class LoginService
    {
        private readonly IRepository<User> _repository;
        protected UserLogService _userLog = new UserLogService();
        public LoginService()
        {
            _repository = new Repository<User>();
        }
        /// <summary>
        /// 登录系统
        /// </summary>
        /// <param name="username">用户名</param>
        /// <param name="password">密码</param>
        /// <param name="verifyCode">验证码</param>
        /// <returns></returns>
        public Result Login(string username, string password, string verifyCode)
        {
            Result result = new Result() { Success = false };
            try
            {
                // 核对验证码
                //if (!CheckVerifyCode(verifyCode))
                //{
                //    result.Message = "验证码错误";
                //    return result;
                //}

                // 根据用户名获取用户
                var user = _repository.QueryFirstOrDefault(
                    "SELECT * FROM [Sys_User] WHERE UserName=@UserName and IsDeleted=0",
                    new { @UserName = username });

                if (!string.IsNullOrEmpty(user?.UserName)) // 用户不为空
                {
                    User update_user = _repository.Get(user.Id);
                    if (user.IsLock == true)
                    {
                        result.Message = "当前用户已经锁定";
                        return result;
                    }
                    var _loginErrorCount = ZCookies.GetCookies(user.UserName + "_loginErrorCount");
                    if (string.IsNullOrWhiteSpace(_loginErrorCount))
                    {
                        _loginErrorCount = "0";
                    }
                    var loginErrorCount = int.Parse(_loginErrorCount);
                    if (loginErrorCount >= (int)UserMaxErrorCount.密码错误次数)
                    {
                        #region ??低调更新(并记录最后一次登录时间)
                        update_user.IsLock = true;
                        update_user.LastLoginTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                        _repository.Update(update_user);
                        #endregion

                        SetLoginLog(user.Id, (int)UserLoginState.锁定, username);//记录登录日志
                        ZCookies.DelCookie(user.UserName + "_loginErrorCount");
                        result.Message = "当前用户已经锁定";
                        return result;
                    }
                    if (!user.UserPWD.Equals(new Symmetric().Encrypto(password))) // 输入密码不正确
                    {
                        ZCookies.WriteCookies(user.UserName + "_loginErrorCount", 60, Convert.ToString(loginErrorCount + 1));
                        SetLoginLog(user.Id, (int)UserLoginState.失败, username);  //记录登录日志
                        result.Message = "密码错误";
                        return result;
                    }

                    // 登录成功
                    int[] roleIds = null; // 用户角色ID数组
                    string[] roleCodes = null; //用户角色编码数组
                    string[] roleNames = null;//角色名称集合
                    // 查询用户角色
                    var userRoles = new UserRoleTBService().GetUserRoleList(user.Id).ToArray();
                    if (userRoles != null && userRoles.Length > 0)
                    {
                        roleIds = new int[userRoles.Count()];
                        roleCodes = new string[userRoles.Count()];
                        roleNames = new string[userRoles.Count()];
                        for (int i = 0; i < userRoles.Length; i++)
                        {
                            roleIds[i] = userRoles[i].RoleID;
                            roleCodes[i] = userRoles[i]?.RoleCode;
                            roleNames[i] = userRoles[i]?.RoleName;
                        }
                    }
                    LoginUser model = new LoginUser()
                    {
                        UserID = user.Id,
                        UserName = user.UserName,
                        RealName = user.RealName,
                        Sex = string.IsNullOrWhiteSpace(user.Sex) == true ? 0 : int.Parse(user.Sex),//空白的默认为0
                        ProfilePhoto = user.UserPhoto,
                        RoleIds = roleIds,
                        RoleCodes = roleCodes,
                        RoleNames = roleNames,
                    };
                    var effectiveHours = ZConfig.GetConfigInt("LoginEffectiveHours"); // 获取Web.config中配置的用户登录有效小时数
                    UserAuthentication.SignIn(username, model, effectiveHours * 60);  // 写入用户身份验证票证
                    GetOnline(username);
                    SetLoginLog(user.Id, (int)UserLoginState.成功, username);//记录登录日志

                    #region 记录最后一次成功登录时间
                    update_user.LastLoginTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    _repository.Update(update_user);
                    #endregion
                    result.Success = true;
                    result.Message = "登录成功";
                    return result;
                }
                else // 未找到用户
                {
                    SetLoginLog(0, (int)UserLoginState.失败, username);//记录登录日志
                    result.Message = "用户名错误";
                    return result;
                }
            }
            catch (Exception ex)
            {
                result.Success = false;
                result.Message = ex.Message;
                return result;
            }
        }

        /// <summary>
        /// 核对验证码
        /// </summary>
        /// <param name="verifyCode"></param>
        /// <returns></returns>
        protected bool CheckVerifyCode(string verifyCode)
        {
            var vc = new VerifyCode();
            return vc.CheckVerifyCode(verifyCode);
        }

        /// <summary>
        /// 注销
        /// </summary>
        /// <returns></returns>
        public void Logout()
        {
            SetLoginLog(UserAuthentication.GetCurrentUser().UserID, (int)UserLoginState.退出);
            // 删除用户菜单权限Session
            ZSession.Remove(ZConfig.GetConfigString("MenuSessionName"));
            // 删除身份验证票证
            UserAuthentication.SingOut();
        }

        /// <summary>
        /// 记录登录信息日志
        /// </summary>
        public bool SetLoginLog(int uid = 0, int logState = 0, string uname = "")
        {
            try
            {
                User user = null;
                //用户名、姓名
                string UserName = string.Empty;
                string RealName = string.Empty;
                string UserPass = string.Empty;
                if (uid > 0)
                {
                    user = new UserService().Get(uid) ?? null;
                    UserName = user?.UserName;
                    RealName = user?.RealName;
                    UserPass = user?.UserPWD;
                }
                else
                {
                    UserName = uname;  //用户名错误:游客登录否？？
                }
                //日志信息
                var loginlog = new UserLog()
                {
                    UserName = UserName,
                    UserPWD = UserPass,
                    State = Convert.ToString(logState),
                    IP = ZHttp.ClientIP,
                    Time = DateTime.Now,
                    Referer = HttpContext.Current.Request.UrlReferrer.ToString(),
                    UserAgent = HttpContext.Current.Request.UserAgent,
                    RealName = RealName
                };
                return _userLog.Add(loginlog);
            }
            catch
            {
                throw;
            }
        }
        /// <summary>
        /// 限制用户异常登录
        /// </summary>
        /// <returns></returns>
        private void GetOnline(string Name)
        {
            Hashtable SingleOnline = (Hashtable)HttpContext.Current.Application["Online"];
            if (SingleOnline == null)
                SingleOnline = new Hashtable();
            if (SingleOnline.ContainsKey(Name))
            {
                SingleOnline[Name] = HttpContext.Current.Session.SessionID;
            }
            else
                SingleOnline.Add(Name, HttpContext.Current.Session.SessionID);

            HttpContext.Current.Application.Lock();
            HttpContext.Current.Application["Online"] = SingleOnline;
            HttpContext.Current.Application.UnLock();
        }

    }
}
